﻿using bitzhuwei.Compiler;

namespace bitzhuwei.GLSLFormat.TestConsole {
    internal class Program {
        static void Main(string[] args) {
            //DumpGLSLst(args); return;
            Console.WriteLine("Hello, GLSLFormat Console!");
            var compiler = new bitzhuwei.GLSLFormat.CompilerGLSL();
            var searchPattern = "*";
            var shaderFiles = Directory.GetFiles(@".\..\..\..\Shaders", searchPattern, SearchOption.AllDirectories);
            foreach (var fileName in shaderFiles) {
                var tail = fileName.ToLower();
                if (!(tail.EndsWith(".vs")
                    || tail.EndsWith(".tc")
                    || tail.EndsWith(".te")
                    || tail.EndsWith(".gs")
                    || tail.EndsWith(".fs")
                    || tail.EndsWith(".cs")
                    || tail.EndsWith(".ss"))) /* .ss means some shaders */{
                    continue;
                }

                Console.WriteLine($"Processing {fileName}");
                var sourceCode = File.ReadAllText(fileName);
                //var tokens = compiler.Analyze(sourceCode);
                var tokens = compiler.BeginAnalyze();// now tokens is empty
                using (var reader = new StringReader(sourceCode)) {
                    while (true) {
                        var line = reader.ReadLine();
                        if (line == null) { break; }
                        compiler.ContinueAnalyze(line);
                    }
                }
                compiler.FinishAnalyze();// now tokens is complete
                var syntaxTree = compiler.Parse(tokens);
                if (syntaxTree.root == null) { throw new Exception(syntaxTree.ToString()); }
                var translationUnits = compiler.Extract(syntaxTree, tokens, sourceCode);
                ArgumentNullException.ThrowIfNull(translationUnits);
                using (var writer = new StreamWriter($"{fileName}.format")) {
                    var context = new FormatContext(tokens, tabUnit: 4, tabCount: 0);
                    translationUnits.Format(writer, context);
                }
                using (var writer = new StreamWriter($"{fileName}.yield")) {
                    var context = new FormatContext(tokens, tabUnit: 4, tabCount: 0);
                    foreach (var item in translationUnits.YieldTokens(writer, context)) { }
                }
                using (var writer = new StreamWriter($"{fileName}.full")) {
                    var context = new FormatContext(tokens, tabUnit: 4, tabCount: 0);
                    translationUnits.FullFormat(new BlankConfig(inlineBlank: 0, forceNewline: false), writer, context);
                }
                using (var writer = new StreamWriter($"{fileName}.tree")) {
                    syntaxTree.root.Print(writer
#if DEBUG
                        , GLSLFormat.CompilerGLSL.stArray
#else 
                        , null
#endif
                        );
                }
            }

            Console.WriteLine("done.");
        }

        /// <summary>
        /// dump GLSL.st from text in GLSLangSpec.4.60.pdf
        /// </summary>
        /// <param name="args"></param>
        static void DumpGLSLst(string[] args) {
            AddTail();
            AddPipe();
            // 3: manually merge statement and statement_no_new_scope
            // 3: manually merge compound_statement and compound_statement_no_new_scope
        }
        static void AddPipe() {
            using (var writer = new StreamWriter("GLSL4.60.8.st.raw")) {
                using (var reader = new StreamReader("Shader.raw2")) {
                    var colon = false;
                    while (!reader.EndOfStream) {
                        var line = reader.ReadLine();
                        if (colon) {
                            writer.Write("      "); writer.WriteLine(line);
                        }
                        else {
                            if (line.EndsWith(":") || line.EndsWith(";")) {
                                writer.WriteLine(line);
                            }
                            else {
                                writer.Write("    | "); writer.WriteLine(line);
                            }
                        }

                        colon = line.EndsWith(":");
                    }
                }
            }
        }
        static void AddTail() {
            using (var writer = new StreamWriter("shader.raw2")) {
                using (var reader = new StreamReader("Shader.raw")) {
                    var first = true;
                    while (!reader.EndOfStream) {
                        var line = reader.ReadLine();
                        if (line.EndsWith(":")) {
                            if (first) {
                                first = false;
                            }
                            else {
                                writer.WriteLine(" ;");
                            }
                        }
                        writer.WriteLine(line);
                    }
                    writer.WriteLine(" ;");
                }
            }
        }
    }
}
